﻿using System;
using System.IO.Ports;

namespace Blue_Rogue_Remote
{
    /// <summary>
    /// Communication controller between mobile and robot
    /// </summary>
    public class BTController
    {
        public delegate void StringHandler(string msg);

        #region fields
        private SerialPort _serial;
        private string _portName = "COM8";
        private int _baudRate = 9600;
        private Parity _parity = Parity.None;
        private int _dataBits = 8;
        private StopBits _stopBits = StopBits.One;
        #endregion

        #region properties
        /// <summary>
        /// Gets or Sets COM portname
        /// </summary>
        public string Port { get { return _portName; } set { _portName = value; } }

        /// <summary>
        /// Gets or Sets Baud rate
        /// </summary>
        public int Baud { get {return _baudRate ;} set {_baudRate = value ;} }

        /// <summary>
        /// Gets or Sets Parity
        /// </summary>
        public Parity Parity { get {return _parity;} set {_parity = value ;} }

        /// <summary>
        /// Gets or Sets Stop bits
        /// </summary>
        public StopBits StopBits { get { return _stopBits; } set {_stopBits = value ;} }

        /// <summary>
        /// Gets or Sets Data bits
        /// </summary>
        public int DataBits { get { return _dataBits; } set {_dataBits = value ;} }

        #endregion

        #region events
        /// <summary>
        /// Occurs when data recieved
        /// </summary>
        public event StringHandler DataReceived;
        #endregion

        #region ctor
        /// <summary>
        /// CTor
        /// </summary>
        public BTController()
        {
            _serial = new SerialPort(Port, Baud, this.Parity, DataBits, this.StopBits);
            _serial.DataReceived += new SerialDataReceivedEventHandler(_serial_DataReceived);
        }
        #endregion

        #region init functions
        /// <summary>
        /// Initialize serial connection with active configuration
        /// </summary>
        private void InitConnection()
        {
            if (_serial.IsOpen)
                _serial.Close();

            _serial.PortName = this.Port;
            _serial.BaudRate = this.Baud;
            _serial.Parity = this.Parity;
            _serial.StopBits = this.StopBits;
            _serial.DataBits = this.DataBits;

        }
        #endregion

        #region members
        /// <summary>
        /// Connect to serial
        /// </summary>
        /// <returns>true if connected</returns>
        public bool Connect()
        {
            if (_serial.IsOpen)
                _serial.Close();
            
            try
            {
                InitConnection();
                _serial.Open();

                return true;
            }
            catch (Exception)
            {
                return false;
                
            }
        }

        

        /// <summary>
        /// Sends data to robot
        /// </summary>
        /// <param name="data">byte containing a nibble for direction and a nibble for speed</param>
        /// <returns>true if send</returns>
        public bool Send(byte data)
        {
            if (!_serial.IsOpen)
                return false;

            byte[] temp = new byte[1];
            temp[0] = data;

            try
            {
                _serial.Write(temp, 0, 1);
                return true;
            }
            catch (Exception)
            {
                return false;

            }
        }

        /// <summary>
        /// Sends a string to robot
        /// </summary>
        /// <param name="data">data string</param>
        /// <returns>true if send</returns>
        public bool Send(string data)
        {
            if (!_serial.IsOpen)
                return false;

            try
            {
                _serial.Write(data);
                return true;
            }
            catch (Exception)
            {
                return false;

            }
        }

        /// <summary>
        /// Disconnect serial connection
        /// </summary>
        /// <returns>true if disconnected</returns>
        public bool Disconnect()
        {
            try
            {
                if (_serial.IsOpen)
                    _serial.Close();

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Get all availible COM port names
        /// </summary>
        /// <returns>String array with availible COM ports</returns>
        public string[] GetPortNames()
        {
            return SerialPort.GetPortNames();
        }
        #endregion

        #region event handlers
        /// <summary>
        /// Data received event handler
        /// </summary>
        private void _serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int bufSize = _serial.ReadBufferSize;

            byte[] buffer = new byte[bufSize];

            _serial.Read(buffer, 0, bufSize);
            _serial.DiscardInBuffer();

            string str = "";

            try
            {
                System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
                str = enc.GetString(buffer, 0, bufSize);
                if (DataReceived != null)
                    DataReceived(str);
            }
            catch (Exception)
            {

            }


        }
        #endregion
    }
}
